/**
**************************************************************************************
*Founder Effect                                                                      *
*Copyright (C) 2006-2007, 5d Studios (www.5d-Studios.com)                            *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#include "stdafx.h"
#include <algorithm>
#include <fstream>

#include "ConsoleFunctions.h"
#include "shared/StringUtil.h"

#include "Kernel.h"

extern Kernel* g_kernel;

Exec_f::Exec_f()
{

}
/**
====================
Execute this command
====================
*/
void Exec_f::Exec(std::string &file)
{
    if ( ParseFile( file ) )
        g_kernel->LPrintf( ("Error loading " + file).c_str() );
}

/**
=================== 
Parse the input script file
===================
*/
int Exec_f::ParseFile(std::string &file)
{
    // open up the file
    std::ifstream stream;
    try {
        stream.open(file.c_str() );
    } catch(...) {
        return 1;
    }
    if ( stream.bad() ) {
        stream.close();
        return 1;
    }
    if ( !stream )
    {
        return 1;
    }
   

    /**
     * Try readin the file
     */
    std::string line="";
    char c;

    while( !stream.eof() )
    {   
        c = stream.get();

        if ( c == '%' || c == 10 )
        {
            // read until newline or eof
            while(!stream.eof() && c != 10 ) {
                c = stream.get();
            }
            continue;
        }
        // if we reached the end of an exp
        // execute it
        if ( c == ';' ) {
            g_kernel->GetConsole()->Exec( line );
            line.clear();
            continue;
        }
        line += (char)c;
    }
    // close the stream
    stream.close();
    return 0;
}

    /*---------------------------------------------------
        Quit Command
    ---------------------------------------------------*/

void Exit_f::Exec(std::string &s) 
{
    g_kernel->StopLoop();
}

    /*---------------------------------------------------
        Clear Command
    ---------------------------------------------------*/

void Clear_f::Exec(std::string &s) 
{
    if ( g_kernel )
    {
        Console* console = g_kernel->GetConsole(); 
        console_t* cons = console->GetDisplay();
        
        cons->Default();
    }
}

    /*---------------------------------------------------
        Echo Command
    ---------------------------------------------------*/

void Echo_f::Exec(std::string &s) 
{
    g_kernel->LPrintf( s.c_str() );
}

    /*---------------------------------------------------
        Set Command
    ---------------------------------------------------*/

void Set_f::Exec(std::string &cmd ) 
{
    std::string name;
    StringUtil token(cmd);

    // parse the cvar name
    if ( token.HasNext() ) {
        name = token.GetNext();   
        if( !g_kernel->GetCvars()->IsValid(name) ) {
            g_kernel->LPrintf( ("Parse error, invalid cvar name --> " + name).c_str());
            return;
        } 
    }
    else
    {
        g_kernel->LPrintf( ("Parse error, no cvar name specified! --> " + cmd).c_str());
        return;
    }

    std::string str;
    std::string s[3];
    int numberOfTokens = token.Size();
    switch( numberOfTokens )
    {
    case 0: 
        g_kernel->LPrintf( g_kernel->GetCvars()->GetStringValue(name).c_str() );
        break;
    case 1: 
        str = token.GetNext();
        // register it
        if( !g_kernel->GetCvars()->SetCvarValue( name ,  str) )
            g_kernel->LPrintf( (name+ " is write protected").c_str());
        break;
    case 2:
        str  = token.GetNext();
        str += " " + token.GetNext();

        // register it
        if( !g_kernel->GetCvars()->SetCvarValue( name , str) )
            g_kernel->LPrintf( (name+ " is write protected").c_str());
        break;
    case 3:
        
        s[0] = token.GetNext();
        s[1] = token.GetNext();
        s[2] = token.GetNext();

        if ( StringUtil::IsNumber( s[0] ) && StringUtil::IsNumber( s[1] ) && StringUtil::IsNumber( s[2] ) )
        {
            MVector3f v;
            v.set( StringUtil::ToFloat( s[0] ), StringUtil::ToFloat( s[1] ), StringUtil::ToFloat( s[2] ) );
            // register it
            if( !g_kernel->GetCvars()->SetCvarValue(name , v) )
                g_kernel->LPrintf( (name+ " is write protected").c_str());
        } 
        else
        {
            str = s[0] + " " + s[1] + " " + s[2];
            // register it
            if( !g_kernel->GetCvars()->SetCvarValue(name , str) )
                g_kernel->LPrintf( (name+ " is write protected").c_str());
        }
        break;
    default:
        if ( token.HasNext() ) 
            str = token.GetNext();
        
        for(int i=0; i< numberOfTokens-1; ++i )
            str += " " + token.GetNext();

        // register it
        if( !g_kernel->GetCvars()->SetCvarValue(name , str) )
            g_kernel->LPrintf( (name+ " is write protected").c_str());
        break;

    };
       
}

    /*---------------------------------------------------
        Create Command
    ---------------------------------------------------*/

//void Create_f::Exec(std::string &s)
//{
//    std::string name ="", value = "";
//    StringUtil token(s);
//    // parse the cvar name
//    if ( token.HasNext() ) {
//        name = token.GetNext();   
//    } 
//    else
//    {
//        g_kernel->LPrintf( ("Parse error, no cvar name specified! --> " + s).c_str());
//        return;
//    }
//
//    // get the value
//    if ( token.HasNext() ) {
//        value = token.GetNext();
//    }
//    else
//    {
//        g_kernel->LPrintf( ("Parse error, no cvar value specified! --> "+ s).c_str());
//        return;
//    }
//    // register it -we only allow dynamic cvars that are saveable
//    g_kernel->GetCvars()->RegisterCvar( name , value, (float)atof(value.c_str()), CVAR_SAVE );
//    g_kernel->LPrintf( ("Cvar created: " + name + " " + value).c_str() );
//}



    /*---------------------------------------------------
        Log Command
    ---------------------------------------------------*/

void Log_f::Exec(std::string &s)
{
    int v = (float)atoi(s.c_str());
    
    if ( v < 0 )
        v = 0;
    else if ( v > 0 )
        v = 1;

    g_kernel->GetCvars()->SetCvarValue("logger", v );
    g_kernel->GetConsole()->SetLog( (bool)v );
}


    /*---------------------------------------------------
        Run Command
    ---------------------------------------------------*/

void Run_f::Exec(std::string &s)
{
    if ( s.size() )
        g_kernel->GetScriptEngine()->RunFile( s );
    else
        g_kernel->LPrintf("<usage> run \"script_file\"");
}